package com.springboot.webdemo.core.utils;

import com.springboot.webdemo.core.result.JSONTreeNode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author 余凯
 *  使用说明：将转换成树结点的实体实现Entity2TreeInter接口，生成树时，调用getTreeJson方法，并传入
 *  List<已实现JSONTreeNode接口的类>对象即可得到JSON的list
 */
public class Entity2TreeUtils {
	
	public static <T extends JSONTreeNode> List<JSONTreeNode> getTreeJson(List<T> e2tList, Long pId) {
		/**
		 * 定义“数组-链表”，该数组链表的每一项相当于一深度为2的小树
		 * Map的key相当于“数组”的某一项，Map的value相当于该key所拥有的“链表”
		 * 这里，key为父节点ID，list为具有相同父节点ID的所有同级子节点实体list（属于该父节点的所有子节点）
		 */
		Map<Integer, List<JSONTreeNode>> arrayListMap = new HashMap<Integer, List<JSONTreeNode>>();

		for (JSONTreeNode e : e2tList) {
			Integer parentId = e.getParentId();
			// 获取当前遍历结点的父ID，并判断该父节点的数组链表项是否存在，如果该“数组项-链表项”不存在，则新建一个，并放入“数组-链表”
			if (arrayListMap.get(parentId) == null) {
				List<JSONTreeNode> list = new ArrayList<JSONTreeNode>();
				list.add(e);
				arrayListMap.put(parentId, list);
			} else {
				List<JSONTreeNode> valueList = arrayListMap.get(parentId);
				valueList.add(e);
				arrayListMap.put(parentId, valueList);
			}
		}
		// 以上，至此，第一遍遍历完毕，非叶子节点都拥有一个“数组-链表项”，也即“最小的树”已创建完毕

		// 以下，对“数组链表”Map进行遍历，更改“最小的树”的从属关系（更改指针指向），也即把所有小树组装成大树
		for (Map.Entry<Integer, List<JSONTreeNode>> entry : arrayListMap.entrySet()) {
			// 获取当前遍历“数组项-链表项”的链表项，并对链表项进行遍历，从“数组-链表”小树中找到它的子节点，并将该子节点加到该小树的children中
			List<JSONTreeNode> smallTreeList = new ArrayList<JSONTreeNode>();
			smallTreeList = entry.getValue();
			int nodeListSize = smallTreeList.size();
			for (int i = 0; i < nodeListSize; i++) {
				Integer findID = smallTreeList.get(i).getId();
				List<JSONTreeNode> findList = arrayListMap.get(findID);
				// 以下操作不能取出对象存放在变量中，否则将破坏树的完整性
				smallTreeList.get(i).setChildren(findList);
			}
		}
		
		// 获取以pId为父Id的链表项，该链表项是根节点实体，里面已封装好各子节点，可以由于多个根节点，即这些根结点的父Id都为pId
		List<JSONTreeNode> rootNodeList = arrayListMap.get(pId);

		//JSONArray jsonArray = JSONArray.fromObject(rootNodeList);
		return rootNodeList;
	}
	
	/**
	  * 根据传入的List转换为 Map，父模块id为key,子模块列表为value              
	  * @param e2tList
	  * @return Map<Long,List<JSONTreeNode>> 
	  * @Author 余凯
	  * @date 2014-11-30 下午4:01:29    
	  * @throws
	 */
	public static <T extends JSONTreeNode> Map<Integer, List<JSONTreeNode>> getTreeMap(List<T> e2tList) {
		/**
		 * 定义“数组-链表”，该数组链表的每一项相当于一深度为2的小树
		 * Map的key相当于“数组”的某一项，Map的value相当于该key所拥有的“链表”
		 * 这里，key为父节点ID，list为具有相同父节点ID的所有同级子节点实体list（属于该父节点的所有子节点）
		 */
		Map<Integer, List<JSONTreeNode>> arrayListMap = new HashMap<Integer, List<JSONTreeNode>>();

		for (JSONTreeNode e : e2tList) {
			Integer parentId = e.getParentId();
			// 获取当前遍历结点的父ID，并判断该父节点的数组链表项是否存在，如果该“数组项-链表项”不存在，则新建一个，并放入“数组-链表”
			if (arrayListMap.get(parentId) == null) {
				List<JSONTreeNode> list = new ArrayList<JSONTreeNode>();
				list.add(e);
				arrayListMap.put(parentId, list);
			} else {
				List<JSONTreeNode> valueList = arrayListMap.get(parentId);
				valueList.add(e);
				arrayListMap.put(parentId, valueList);
			}
		}
		// 以上，至此，第一遍遍历完毕，非叶子节点都拥有一个“数组-链表项”，也即“最小的树”已创建完毕

		// 以下，对“数组链表”Map进行遍历，更改“最小的树”的从属关系（更改指针指向），也即把所有小树组装成大树
		for (Map.Entry<Integer, List<JSONTreeNode>> entry : arrayListMap.entrySet()) {
			// 获取当前遍历“数组项-链表项”的链表项，并对链表项进行遍历，从“数组-链表”小树中找到它的子节点，并将该子节点加到该小树的children中
			List<JSONTreeNode> smallTreeList = new ArrayList<JSONTreeNode>();
			smallTreeList = entry.getValue();
			int nodeListSize = smallTreeList.size();
			for (int i = 0; i < nodeListSize; i++) {
				Integer findID = smallTreeList.get(i).getId();
				List<JSONTreeNode> findList = arrayListMap.get(findID);
				// 以下操作不能取出对象存放在变量中，否则将破坏树的完整性
				smallTreeList.get(i).setChildren(findList);
			}
		}

		return arrayListMap;
	}
	
	/**
	  * 组成只有一个根结节的树型列表              
	  * @param e2tList
	  * @return List<JSONTreeNode> 
	  * @Author 余凯
	  * @date 2014-12-9 下午10:35:53    
	  * @throws
	 */
	public static <T extends JSONTreeNode> List<JSONTreeNode> buildTreeJson(List<T> e2tList) {
		/**
		 * 定义“数组-链表”，该数组链表的每一项相当于一深度为2的小树
		 * Map的key相当于“数组”的某一项，Map的value相当于该key所拥有的“链表”
		 * 这里，key为父节点ID，list为具有相同父节点ID的所有同级子节点实体list（属于该父节点的所有子节点）
		 */
		Map<Integer, List<JSONTreeNode>> arrayListMap = new HashMap<Integer, List<JSONTreeNode>>();

		for (JSONTreeNode e : e2tList) {
			Integer parentId = e.getParentId();
			// 获取当前遍历结点的父ID，并判断该父节点的数组链表项是否存在，如果该“数组项-链表项”不存在，则新建一个，并放入“数组-链表”
			if (arrayListMap.get(parentId) == null) {
				List<JSONTreeNode> list = new ArrayList<JSONTreeNode>();
				list.add(e);
				arrayListMap.put(parentId, list);
			} else {
				List<JSONTreeNode> valueList = arrayListMap.get(parentId);
				valueList.add(e);
				arrayListMap.put(parentId, valueList);
			}
		}
		// 以上，至此，第一遍遍历完毕，非叶子节点都拥有一个“数组-链表项”，也即“最小的树”已创建完毕
		List<Integer> list = new ArrayList<Integer>();
		// 以下，对“数组链表”Map进行遍历，更改“最小的树”的从属关系（更改指针指向），也即把所有小树组装成大树
		for (Map.Entry<Integer, List<JSONTreeNode>> entry : arrayListMap.entrySet()) {
			// 获取当前遍历“数组项-链表项”的链表项，并对链表项进行遍历，从“数组-链表”小树中找到它的子节点，并将该子节点加到该小树的children中
			List<JSONTreeNode> smallTreeList = new ArrayList<JSONTreeNode>();
			smallTreeList = entry.getValue();
			int nodeListSize = smallTreeList.size();
			for (int i = 0; i < nodeListSize; i++) {
				Integer findID = smallTreeList.get(i).getId();
				List<JSONTreeNode> findList = arrayListMap.get(findID);
				// 以下操作不能取出对象存放在变量中，否则将破坏树的完整性
				smallTreeList.get(i).setChildren(findList);
				list.add(findID);
			}
		}
		//移除已找到父节点的子节点
		if(list.size() > 0) {
			for(Integer findId : list) {
				arrayListMap.remove(findId);
			}
		}
		//把多个根节点再组成一颗树
		List<JSONTreeNode> treeList = new ArrayList<JSONTreeNode>();
		for(Map.Entry<Integer, List<JSONTreeNode>> entry : arrayListMap.entrySet()) {
			List<JSONTreeNode> nlist = entry.getValue();
			for(JSONTreeNode n: nlist) {
				treeList.add(n);
			}
		}
		//JSONArray jsonArray = JSONArray.fromObject(rootNodeList);
		return treeList;
	}
}
